home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / glimpse-2.1 / split.c < prev   
C/C++ Source or Header  |  1995-05-16  |  19KB  |  557 lines

  1. /* Copyright (c) 1994 Burra Gopal, Udi Manber.  All Rights Reserved. */
  2.  
  3. #include "glimpse.h"
  4.  
  5. extern CHAR *getword();
  6. extern int checksg();
  7. extern int D;
  8. extern CHAR GProgname[MAXNAME];
  9. extern FILE *debug;
  10. extern int StructuredIndex;
  11. extern int WHOLEFILESCOPE;
  12. extern int ByteLevelIndex;
  13. extern int ComplexBoolean;
  14. extern int foundattr;
  15.  
  16. /* returns where it found the distinguishing token: until that from prev value of begin is the current pattern (not just the "words" in it) */
  17. CHAR *
  18. parse_flat(begin, end, prev, next)
  19.     CHAR    *begin;
  20.     CHAR    *end;
  21.     int    prev;
  22.     int    *next;
  23. {
  24.     if (begin > end) {
  25.         *next = prev;
  26.         return end;
  27.     }
  28.  
  29.     if (prev & ENDSUB_EXP) prev &= ~ATTR_EXP;
  30.     if ((prev & ATTR_EXP) && !(prev & VAL_EXP)) prev |= VAL_EXP;
  31.  
  32.     while (begin <= end) {
  33.         if (*begin == ',') {
  34.             prev |= OR_EXP;
  35.             prev |= VAL_EXP;
  36.             prev |= ENDSUB_EXP;
  37.             if (prev & AND_EXP) {
  38.                 fprintf(stderr, "%s: parse error at character '%c'\n", GProgname, *begin);
  39.                 return NULL;
  40.             }
  41.             *next = prev;
  42.             return begin;
  43.         }
  44.         else if (*begin == ';') {
  45.             prev |= AND_EXP;
  46.             prev |= VAL_EXP;
  47.             prev |= ENDSUB_EXP;
  48.             if (prev & OR_EXP) {
  49.                 fprintf(stderr, "%s: parse error at character '%c'\n", GProgname, *begin);
  50.                 return NULL;
  51.             }
  52.             *next = prev;
  53.             return begin;
  54.         }
  55.         else if (*begin == '=') {
  56.             if (StructuredIndex <= 0) begin++;    /* don't care about = since just another character */
  57.             else {
  58.                 if (prev & ATTR_EXP) {
  59.                     fprintf(stderr, "%s: syntax error: only ',' and ';' can follow 'attribute=value'\n", GProgname);
  60.                     return NULL;
  61.                 }
  62.                 prev |= ATTR_EXP;    /* remains an ATTR_EXP until a new ',' OR ';' */
  63.                 prev &= ~VAL_EXP;
  64.                 *next = prev;
  65.                 return begin;
  66.             }
  67.         }
  68.         else if (*begin == '\\') begin ++;    /* skip two things */
  69.         begin++;
  70.     }
  71.  
  72.     *next = prev;
  73.     return begin;
  74. }
  75.  
  76. int
  77. split_pattern_flat(GPattern, GM, APattern, terminals, pnum_terminals, pGParse, num_attr)
  78.     CHAR    *GPattern;
  79.     int    GM;
  80.     CHAR    *APattern;
  81.     ParseTree terminals[];
  82.     int    *pnum_terminals;
  83.     int    *pGParse;    /* doesn't interpret it as a tree */
  84.     int    num_attr;
  85. {
  86.     int   j, k = 0, l = 0, len = 0;
  87.     int   current_attr;
  88.     CHAR  *buffer;
  89.     CHAR  *buffer_pat;
  90.     CHAR  *buffer_end;
  91.     char  tempbuf[MAX_LINE_LEN];
  92.  
  93.     memset(APattern, '\0', MAXPAT);
  94.     buffer = GPattern;
  95.     buffer_end = buffer + GM;
  96.     j=0;
  97.     *pGParse = 0;
  98.     current_attr = 0;
  99.     foundattr = 0;
  100.  
  101.     /*
  102.      * buffer is the runnning pointer, buffer_pat is the place where
  103.      * the distinguishing delimiter was found, buffer_end is the end.
  104.      */
  105.      while (buffer_pat = parse_flat(buffer, buffer_end, *pGParse, pGParse)) {
  106.         /* there is no pattern until after the distinguishing delimiter position: some agrep garbage */
  107.         if (buffer_pat <= buffer) {
  108.             buffer = buffer_pat+1;
  109.             if (buffer_pat >= buffer_end) break;
  110.             continue;
  111.         }
  112.         if ((*pGParse & ATTR_EXP) && !(*pGParse & VAL_EXP)) {    /* fresh attribute */
  113.             foundattr=1;
  114.             memcpy(tempbuf, buffer, buffer_pat - buffer);
  115.             tempbuf[buffer_pat - buffer] = '\0';
  116.             len = strlen(tempbuf);
  117.             for (k = 0; k<len; k++) {
  118.                 if (tempbuf[k] == '\\') {
  119.                     for (l=k; l<len; l++)
  120.                         tempbuf[l] = tempbuf[l+1];
  121.                     len --;
  122.                 }
  123.             }
  124.             if ( ((current_attr = attr_name_to_id(tempbuf, len)) <= 0) || (current_attr >= num_attr)) {
  125.                 buffer[buffer_pat - buffer] = '\0';
  126.                 fprintf(stderr, "%s: unknown attribute name '%s'\n", GProgname, buffer);
  127.                 return -1;
  128.             }
  129.  
  130.             buffer = buffer_pat+1;    /* immediate next character after distinguishing delimiter */
  131.             if (buffer_pat >= buffer_end) break;
  132.             continue;
  133.         }
  134.         else {    /* attribute's value OR raw-value */
  135.             if (*pnum_terminals >= MAXNUM_PAT) {
  136.                 fprintf(stderr, "%s: boolean expression has too many terms\n", GProgname);
  137.                 return -1;
  138.             }
  139.             terminals[*pnum_terminals].op = 0;
  140.             terminals[*pnum_terminals].type = LEAF;
  141.             terminals[*pnum_terminals].terminalindex = *pnum_terminals;
  142.             terminals[*pnum_terminals].data.leaf.attribute = current_attr;    /* default is no structure */
  143.             terminals[*pnum_terminals].data.leaf.value = (CHAR *)malloc(buffer_pat - buffer + 2);
  144.             memcpy(terminals[*pnum_terminals].data.leaf.value, buffer, buffer_pat - buffer);    /* without distinguishing delimiter */
  145.             terminals[*pnum_terminals].data.leaf.value[buffer_pat - buffer] = '\0';
  146.             if (foundattr || WHOLEFILESCOPE) {
  147.                 memcpy(&APattern[j], buffer, buffer_pat - buffer);
  148.                 j += buffer_pat - buffer;    /* NOT including the distinguishing delimiter at buffer_pat, or '\0' */
  149.                 APattern[j++] = (*(buffer_pat + 1) == '\0' ? '\0' : ',');    /* always search for OR, do filtering at the end */
  150. #if    BG_DEBUG
  151.                 fprintf(debug, "current_attr = %d, val = %s\n", current_attr, terminals[*pnum_terminals].data.leaf.value);
  152. #endif    /*BG_DEBUG*/
  153.             }
  154.             else {
  155.                 memcpy(&APattern[j], buffer, buffer_pat + 1 - buffer);
  156.                 j += buffer_pat + 1 - buffer;    /* including the distinguishing delimiter at buffer_pat, or '\0' */
  157.             }
  158.             (*pnum_terminals)++;
  159.         }
  160.         if (*pGParse & ENDSUB_EXP) current_attr = 0;    /* remains 0 until next fresh attribute */
  161.         if (buffer_pat >= buffer_end) break;
  162.         buffer = buffer_pat+1;
  163.     }
  164.     if (buffer_pat == NULL) return -1;    /* got out of while loop because of NULL rather than break */
  165.     APattern[j] = '\0';
  166.  
  167.     if (foundattr || WHOLEFILESCOPE)    /* then search must always be OR since scope is over whole files */
  168.         for (j=0; APattern[j] != '\0'; j++)
  169.             if (APattern[j] == '\\') j++;
  170.             else if (APattern[j] == ';') APattern[j] = ',';
  171.     return(*pnum_terminals);
  172. }
  173.  
  174. extern int is_complex_boolean();    /* use the one in agrep/asplit.c */
  175. extern int get_token_bool();    /* use the one in agrep/newasplit.c */
  176.  
  177. /* Spaces ARE significant: 'a1=v1' and 'a1=v1 ' and 'a1 =v1' etc. are NOT identical */
  178. int
  179. get_attribute_value(pattr, pval, tokenbuf, tokenlen, num_attr)
  180.     int    *pattr, tokenlen;
  181.     CHAR    **pval, *tokenbuf;
  182. {
  183.     CHAR    tempbuf[MAXNAME];
  184.     int    i = 0, j = 0, k = 0, l = 0;
  185.  
  186.     while (i < tokenlen) {
  187.         if (tokenbuf[i] == '\\') {
  188.             tempbuf[j++] = tokenbuf[i++];
  189.             tempbuf[j++] = tokenbuf[i++];
  190.         }
  191.         else if (StructuredIndex) {
  192.             if (tokenbuf[i] == '=') {
  193.                 i++;    /* skip over = : now @ 1st char of value */
  194.                 tempbuf[j] = '\0';
  195.                 for (k=0; k<j; k++) {
  196.                     if (tempbuf[k] == '\\') {
  197.                         for (l=k; l<j; l++)
  198.                             tempbuf[l] = tempbuf[l+1];
  199.                         j --;
  200.                     }
  201.                 }
  202.                 if ( ((*pattr = attr_name_to_id(tempbuf, j)) <= 0) || (*pattr >= num_attr) ) {    /* named a non-existent attribute */
  203.                     fprintf(stderr, "%s: unknown attribute name '%s'\n", GProgname, tempbuf);
  204.                     return 0;
  205.                 }
  206.                 *pval = (CHAR *)malloc(tokenlen - i + 2);
  207.                 memcpy(*pval, &tokenbuf[i], tokenlen - i);
  208.                 (*pval)[tokenlen - i] = '\0';
  209.                 foundattr = 1;
  210.                 return 1;
  211.             }
  212.             else tempbuf[j++] = tokenbuf[i++];    /* consider = as just another char */
  213.         }
  214.         else tempbuf[j++] = tokenbuf[i++];    /* no attribute parsing */
  215.     }
  216.     /* Not a structured expression */
  217.     tempbuf[j] = '\0';
  218.     *pval = (CHAR *)malloc(j + 2);
  219.     memcpy(*pval, tempbuf, j);
  220.     (*pval)[j] = '\0';
  221.     return 1;
  222. }
  223.  
  224. extern destroy_tree();    /* use the one in agrep/newasplit.c */
  225.  
  226. /*
  227.  * Recursive descent; C-style => AND + OR have equal priority => must bracketize expressions appropriately or will go left->right.
  228.  * Also strips out attribute names since agrep doesn't understand them: copies resulting pattern for agrep-ing into apattern.
  229.  * Grammar:
  230.  *     E = {E} | ~a | ~{E} | E ; E | E , E | a
  231.  * Parser:
  232.  *    One look ahead at each literal will tell you what to do.
  233.  *    ~ has highest priority, ; and , have equal priority (left to right associativity), ~~ is not allowed.
  234.  */
  235. ParseTree *
  236. parse_tree(buffer, len, bufptr, apattern, apatptr, terminals, pnum_terminals, num_attr)
  237.     CHAR    *buffer;
  238.     int    len;
  239.     int    *bufptr;
  240.     CHAR    *apattern;
  241.     int    *apatptr;
  242.     ParseTree terminals[];
  243.     int    *pnum_terminals;
  244.     int    num_attr;
  245. {
  246.     int    token, tokenlen;
  247.     CHAR    tokenbuf[MAXNAME];
  248.     int    oldtokenlen;
  249.     CHAR    oldtokenbuf[MAXNAME];
  250.     ParseTree *t, *n, *leftn;
  251.  
  252.     token = get_token_bool(buffer, len, bufptr, tokenbuf, &tokenlen);
  253.     switch(token)
  254.     {
  255.     case    '{':    /* (exp) */
  256.         apattern[(*apatptr)++] = '{';
  257.         if ((t = parse_tree(buffer, len, bufptr, apattern, apatptr, terminals, pnum_terminals, num_attr)) == NULL) return NULL;
  258.         if ((token = get_token_bool(buffer, len, bufptr, tokenbuf, &tokenlen)) != '}') {
  259.             fprintf(stderr, "%s: parse error at offset %d\n", GProgname, *bufptr);
  260.             destroy_tree(t);
  261.             return (NULL);
  262.         }
  263.         apattern[(*apatptr)++] = '}';
  264.         if ((token = get_token_bool(buffer, len, bufptr, tokenbuf, &tokenlen)) == 'e') return t;
  265.         switch(token)
  266.         {
  267.         /* must find boolean infix operator */
  268.         case ',':
  269.         case ';':
  270.             apattern[(*apatptr)++] = token;
  271.             leftn = t;
  272.             if ((t = parse_tree(buffer, len, bufptr, apattern, apatptr, terminals, pnum_terminals, num_attr)) == NULL) return NULL;
  273.             n = (ParseTree *)malloc(sizeof(ParseTree));
  274.             n->op = (token == ';') ? ANDPAT : ORPAT ;
  275.             n->type = INTERNAL;
  276.             n->data.internal.left = leftn;
  277.             n->data.internal.right = t;
  278.             return n;
  279.  
  280.         /* or end of parent sub expression */
  281.         case '}':
  282.             unget_token_bool(bufptr, tokenlen);    /* part of someone else who called me */
  283.             return t;
  284.  
  285.         default:
  286.             destroy_tree(t);
  287.             fprintf(stderr, "%s: parse error at offset %d\n", GProgname, *bufptr);
  288.             return NULL;
  289.         }
  290.  
  291.     /* Go one level deeper */
  292.     case    '~':    /* not exp */
  293.         apattern[(*apatptr)++] = '~';
  294.         if ((token = get_token_bool(buffer, len, bufptr, tokenbuf, &tokenlen)) == 'e') return NULL;
  295.         switch(token)
  296.         {
  297.         case 'a':
  298.             if (*pnum_terminals >= MAXNUM_PAT) {
  299.                 fprintf(stderr, "%s: pattern expression too long (> %d terms)\n", GProgname, MAXNUM_PAT);
  300.                 return NULL;
  301.             }
  302.             n = &terminals[*pnum_terminals];
  303.             n->op = 0;
  304.             n->type = LEAF;
  305.             n->terminalindex = (*pnum_terminals);
  306.             n->data.leaf.value = NULL;
  307.             n->data.leaf.attribute = 0;
  308.             if (!get_attribute_value(&n->data.leaf.attribute, &n->data.leaf.value, tokenbuf, tokenlen, num_attr)) return NULL;
  309.             strcpy(&apattern[*apatptr], n->data.leaf.value);
  310.             *apatptr += strlen(n->data.leaf.value);
  311.             (*pnum_terminals)++;
  312.             n->op |= NOTPAT;
  313.             t = n;
  314.             break;
  315.  
  316.         case '{':
  317.             apattern[(*apatptr)++] = token;
  318.             if ((t = parse_tree(buffer, len, bufptr, apattern, apatptr, terminals, pnum_terminals, num_attr)) == NULL) return NULL;
  319.             if (t->op & NOTPAT) t->op &= ~NOTPAT;
  320.             else t->op |= NOTPAT;
  321.             if ((token = get_token_bool(buffer, len, bufptr, tokenbuf, &tokenlen)) != '}') {
  322.                 fprintf(stderr, "%s: parse error at offset %d\n", GProgname, *bufptr);
  323.                 destroy_tree(t);
  324.                 return NULL;
  325.             }
  326.             break;
  327.  
  328.         default:
  329.             fprintf(stderr, "%s: parse error at offset %d\n", GProgname, *bufptr);
  330.             return NULL;
  331.         }
  332.         /* The resulting tree is in t. Now do another lookahead at this level */
  333.  
  334.         if ((token = get_token_bool(buffer, len, bufptr, tokenbuf, &tokenlen)) == 'e') return t;
  335.         switch(token)
  336.         {
  337.         /* must find boolean infix operator */
  338.         case ',':
  339.         case ';':
  340.             apattern[(*apatptr)++] = token;
  341.             leftn = t;
  342.             if ((t = parse_tree(buffer, len, bufptr, apattern, apatptr, terminals, pnum_terminals, num_attr)) == NULL) return NULL;
  343.             n = (ParseTree *)malloc(sizeof(ParseTree));
  344.             n->op = (token == ';') ? ANDPAT : ORPAT ;
  345.             n->type = INTERNAL;
  346.             n->data.internal.left = leftn;
  347.             n->data.internal.right = t;
  348.             return n;
  349.  
  350.         case '}':
  351.             unget_token_bool(bufptr, tokenlen);
  352.             return t;
  353.  
  354.         default:
  355.             destroy_tree(t);
  356.             fprintf(stderr, "%s: parse error at offset %d\n", GProgname, *bufptr);
  357.             return NULL;
  358.         }
  359.  
  360.     case    'a':    /* individual term (attr=val) */
  361.         if (tokenlen == 0) return NULL;
  362.         memcpy(oldtokenbuf, tokenbuf, tokenlen);
  363.         oldtokenlen = tokenlen;
  364.         token = get_token_bool(buffer, len, bufptr, tokenbuf, &tokenlen);
  365.         switch(token)
  366.         {
  367.         case '}':    /* part of case '{' above: else syntax error not detected but semantics ok */
  368.             unget_token_bool(bufptr, tokenlen);
  369.         case 'e':    /* endof input */
  370.         case ',':
  371.         case ';':
  372.             if (*pnum_terminals >= MAXNUM_PAT) {
  373.                 fprintf(stderr, "%s: pattern expression too long (> %d terms)\n", GProgname, MAXNUM_PAT);
  374.                 return NULL;
  375.             }
  376.             n = &terminals[*pnum_terminals];
  377.             n->op = 0;
  378.             n->type = LEAF;
  379.             n->terminalindex = (*pnum_terminals);
  380.             n->data.leaf.value = NULL;
  381.             n->data.leaf.attribute = 0;
  382.             if (!get_attribute_value(&n->data.leaf.attribute, &n->data.leaf.value, oldtokenbuf, oldtokenlen, num_attr)) return NULL;
  383.             strcpy(&apattern[*apatptr], n->data.leaf.value);
  384.             *apatptr += strlen(n->data.leaf.value);
  385.             n->data.leaf.value[oldtokenlen] = '\0';
  386.             (*pnum_terminals)++;
  387.             if ((token == 'e') || (token == '}')) return n;    /* nothing after terminal in expression */
  388.  
  389.             leftn = n;
  390.             apattern[(*apatptr)++] = token;
  391.             if ((t = parse_tree(buffer, len, bufptr, apattern, apatptr, terminals, pnum_terminals, num_attr)) == NULL) return NULL;
  392.             n = (ParseTree *)malloc(sizeof(ParseTree));
  393.             n->op = (token == ';') ? ANDPAT : ORPAT ;
  394.             n->type = INTERNAL;
  395.             n->data.internal.left = leftn;
  396.             n->data.internal.right = t;
  397.             return n;
  398.  
  399.         default:
  400.             fprintf(stderr, "%s: parse error at offset %d\n", GProgname, *bufptr);
  401.             return NULL;
  402.         }
  403.  
  404.     case    'e':    /* can't happen as I alweys do a lookahead above and renurn current tree if e */
  405.     default:
  406.         fprintf(stderr, "%s: parse error at offset %d\n", GProgname, *bufptr);
  407.         return NULL;
  408.     }
  409. }
  410.  
  411. int
  412. split_pattern(GPattern, GM, APattern, terminals, pnum_terminals, pGParse, num_attr)
  413.     CHAR    *GPattern;
  414.     int    GM;
  415.     CHAR    *APattern;
  416.     ParseTree terminals[];
  417.     int    *pnum_terminals;
  418.     ParseTree **pGParse;
  419.     int    num_attr;
  420. {
  421.     int    bufptr = 0, apatptr = 0, ret, i, j;
  422.  
  423.     foundattr = 0;
  424.     if (is_complex_boolean(GPattern, GM)) {
  425.         ComplexBoolean = 1;
  426.         *pnum_terminals = 0;
  427.         if ((*pGParse = parse_tree(GPattern, GM, &bufptr, APattern, &apatptr, terminals, pnum_terminals, num_attr)) == NULL)
  428.             return -1;
  429.         /* print_tree(*pGParse, 0); */
  430.         APattern[apatptr] = '\0';
  431.         if (foundattr || WHOLEFILESCOPE) {    /* Search in agrep must always be OR since scope is whole file */
  432.             int    i, j;
  433.  
  434.             for (i=0; i<apatptr; i++) {
  435.                 if (APattern[i] == '\\') i++;
  436.                 else if (APattern[i] == ';') APattern[i] = ',';
  437.                 else if ((APattern[i] == '~') || (APattern[i] == '{') || (APattern[i] == '}')) {
  438.                     /* eliminate it from pattern by shifting (including '\0') since agrep must essentially do a flat search */
  439.                     for (j=i; j<apatptr; j++)
  440.                         APattern[j] = APattern[j+1];
  441.                     apatptr --;
  442.                 }
  443.             }
  444.         }
  445.         return *pnum_terminals;
  446.     }
  447.     else {
  448.         for (i=0; i<GM; i++) {
  449.             if (GPattern[i] == '\\') i++;
  450.             else if ((GPattern[i] == '{') || (GPattern[i] == '}')) {
  451.                 /* eliminate it from pattern by shifting (including '\0') since agrep must essentially do a flat search */
  452.                 for (j=i; j<GM; j++)
  453.                     GPattern[j] = GPattern[j+1];
  454.                 GM --;
  455.             }
  456.         }
  457.  
  458.         ComplexBoolean = 0;
  459.         *pnum_terminals = 0;
  460.         if ((ret = split_pattern_flat(GPattern, GM, APattern, terminals, pnum_terminals, (int *)pGParse, num_attr)) == -1)
  461.             return -1;
  462.         return ret;
  463.     }
  464. }
  465.  
  466. int eval_tree();    /* use the one in agrep/newasplit.c */
  467.  
  468. /* MUST CHANGE ALL memgreps TO USE EXEC DIRECTLY IF POSSIBLE (LAST PRIORITY) */
  469.  
  470. /* All borrowed from main.c and are needed for searching the index */
  471. extern    CHAR    *pat_list[MAXNUM_PAT];  /* complete words within global pattern */
  472. extern    int    pat_lens[MAXNUM_PAT];   /* their lengths */
  473. extern    int    pat_attr[MAXNUM_PAT];   /* set of attributes */
  474. extern    int    num_pat;
  475. extern    CHAR    pat_buf[(MAXNUM_PAT + 2)*MAXPAT];
  476. extern    int    pat_ptr;
  477. extern    int    is_mgrep_pat[MAXNUM_PAT];
  478. extern    int    mgrep_pat_index[MAXNUM_PAT];
  479. extern    int    num_mgrep_pat;
  480. extern    int    src_index_set[REAL_PARTITION];
  481. extern    struct offsets **src_offset_table;
  482. extern    int    curr_index_set[REAL_PARTITION];
  483. extern    struct offsets **curr_offset_table;
  484. extern    char    tempfile[];
  485. extern    int    patindex;
  486. extern    int    patbufpos;
  487. extern    ParseTree terminals[MAXNUM_PAT];
  488. extern    int    num_terminals;
  489. extern int INVERSE;    /* agrep's global: need here to implement ~ in index-search */
  490.  
  491. /* [first, last) = C-style range for which we want the words in terminal-values' patterns: 0..num_terminals for !ComplexBoolean, term/term otherwise */
  492. split_terminal(first, last)
  493.     int    first, last;
  494. {
  495.         CHAR    *buffer;
  496.         CHAR    *buffer_new;
  497.         CHAR    *buffer_end;
  498.         CHAR    *bp;
  499.         CHAR    word[MAXNAME];
  500.         int    word_length;
  501.         int    type;
  502.  
  503.     pat_ptr = 0;
  504.     num_mgrep_pat = 0;
  505.     num_pat = 0;
  506.  
  507.     for (; first<last; first++) {
  508.         buffer = terminals[first].data.leaf.value;
  509.         buffer_end = buffer + strlen(terminals[first].data.leaf.value);
  510.  
  511.                 /* Now find out which; are the "words" we can search for in the index: each attr_val can have many words in it: e.g., "AUTHOR=Udi Manber" */
  512.                 while ((buffer_new = getword(word, buffer, buffer_end, NULL)) <= buffer_end) {
  513.                         word_length = strlen(word);
  514.                         if (word_length <= 0) {
  515.                                 buffer = buffer_new;
  516.                                 if (buffer_new >= buffer_end) break;
  517.                                 continue;
  518.                         }
  519.                         if ((type = checksg(word, D, 0)) == -1) return -1;
  520.             if (!type && ComplexBoolean) {
  521.                 fprintf(stderr, "%s: query has complex patterns: cannot search for arbitrary booleans\n", GProgname);
  522.                 return -1;
  523.             }
  524.             if (strlen(word) <= 0) continue;
  525.                         buffer = buffer_new;
  526.                         bp = (CHAR *) malloc(sizeof(CHAR) * word_length + 2);
  527.                         if(bp == NULL) {
  528.                                 fprintf(stderr, "%s: malloc failed in %s:%d\n", GProgname, __FILE__, __LINE__);
  529.                                 return -1;
  530.                         }
  531.                         pat_list[num_pat] = bp;
  532.                         pat_lens[num_pat] = word_length;
  533.                         is_mgrep_pat[num_pat] = type;
  534.                         pat_attr[num_pat] = terminals[first].data.leaf.attribute;
  535.                         if (type) {
  536.                                 strcpy(&pat_buf[pat_ptr], word);
  537.                                 pat_buf[pat_ptr + word_length] = '\n';
  538.                                 pat_buf[pat_ptr + word_length + 1] = '\0';
  539.                                 pat_ptr += (word_length + 1);
  540.                                 mgrep_pat_index[num_mgrep_pat++] = num_pat;
  541.                         }
  542.                         strcpy(pat_list[num_pat], word);
  543.             pat_list[num_pat][word_length] = '\0';
  544.             num_pat ++;
  545. #if     BG_DEBUG
  546.                         fprintf(debug, "word=%s\n", word);
  547. #endif  /*BG_DEBUG*/
  548.                         if(buffer_new >= buffer_end) break;
  549.                         if(num_pat >= MAXNUM_PAT) {
  550.                                 fprintf(stderr, "%s: Warning! too many words in pattern (> %d): ignoring...\n", GProgname, MAXNUM_PAT);
  551.                                 break;
  552.                         }
  553.                 }
  554.     }
  555.     return num_pat;
  556. }
  557.